package cloud.pangui.core.utils;

import cloud.pangui.core.exception.UtilsRuntimeException;
import sun.reflect.generics.reflectiveObjects.ParameterizedTypeImpl;

import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.ArrayList;
import java.util.List;

/**
 * @Auther hepangui
 * @Date 2020/11/5 0005
 */
public class ClassUtils {
	/**
	 * 反射创建对象，支持创建内部类
	 *
	 * @param type
	 * @return
	 */
	public static <T> T newInstance(Class<T> type) {
		try {
			boolean isMemberClass = type.isMemberClass();
			if (!isMemberClass) {
				return type.newInstance();
			}
			List<Class> cs = new ArrayList<>();
			cs.add(type);
			Class cc = type;
			while (cc.isMemberClass()) {
				cs.add(0, cc.getEnclosingClass());
				cc = cc.getEnclosingClass();
			}

			Object current = null;
			for (Class c : cs) {
				if (current == null) {
					current = c.getDeclaredConstructor().newInstance();
				} else {
					current = c.getDeclaredConstructor(current.getClass()).newInstance(current);
				}
			}
			return (T) current;
		} catch (Exception e) {
			throw new UtilsRuntimeException(e);
		}
	}

	/**
	 * 判断是不是接口
	 * @param type
	 * @return
	 */
	public static boolean isInterface(Type type) {
		return type.toString().indexOf("interface ") == 0;
	}

	/**
	 * 判断类是不是一个class
	 * @param type
	 * @return
	 */
	public static boolean isClass(Type type) {
		return type.toString().indexOf("class ") == 0;
	}

	/**
	 * 判断是不是基本类型
	 * @param type
	 * @return
	 */
	public static boolean isPrimitive(Type type) {

		return
				type.toString().equals("int")
						|| type.toString().equals("double")
						|| type.toString().equals("short")
						|| type.toString().equals("long")
						|| type.toString().equals("float")
						|| type.toString().equals("boolean")
						|| type.toString().equals("char")
						|| type.toString().equals("byte")
				;
	}

	/**
	 * 判断是否为泛型
	 *
	 * @param type
	 * @return
	 */
	public static boolean isGenericType(Type type) {
		return type.toString().indexOf("<") > 0;
	}

	/**
	 * 根据名字获取对应的类型  name 来自于type.toString
	 * int  基本类型
	 * class [Ljava.lang.String; 数组
	 * class [Z 基本类型数组
	 * class java.lang.String 正常class
	 * java.util.List<java.lang.Exception[]>  泛型
	 * java.util.Map<java.util.List<java.lang.String>, java.lang.Exception>
	 * @param name
	 * @return
	 * @throws ClassNotFoundException
	 */
	public static Type getType(String name) {
		switch(name){
			case "int": return int.class;
			case "boolean": return boolean.class;
			case "byte": return byte.class;
			case "short": return short.class;
			case "long": return long.class;
			case "char": return char.class;
			case "float": return float.class;
			case "double": return double.class;
		}

		if(name.startsWith("class ") && name.length()>6){
			return forName(name.substring(6).trim());
		}

		if(name.indexOf("<")>-1){
			return getParameterizedType(name);
		}

		throw new IllegalArgumentException("类:"+name+"无法找到");
	}

	/**
	 * 获取泛型type
	 * @param name
	 */
	public static ParameterizedType getParameterizedType(String name) {
		int begin = name.indexOf("<");
		int end = name.lastIndexOf(">");
		String className = name.substring(0,begin);
		String paraTypes = name.substring(begin+1,end);
		Class aClass = forName(className);
		String[] split = paraTypes.split(",");
		Type [] innerTypes = new Type[split.length];
		for (int i = 0; i < split.length; i++) {
			String s = split[i];

			if(s.indexOf("<")>-1){
				innerTypes[i] = getParameterizedType(s);
			}else{
				if(s.endsWith("[]")){
					s = "class [L"+s.substring(0,s.length()-2).trim()+";";
				}else{
					s = "class "+s;
				}
				innerTypes[i] = getType(s);
			}
		}
		ParameterizedTypeImpl parameterizedType = ParameterizedTypeImpl.make(aClass,innerTypes,null);
		return parameterizedType;
	}


	/**
	 * 加载类
	 * 不能传数组类，基本类型
	 * @param className 类名
	 */
	public static Class forName(String className) {
		try {
			return Thread.currentThread().getContextClassLoader().loadClass(className);
		} catch (Exception e) {
			throw new UtilsRuntimeException(e);
		}
	}

}
